package cn.est.controller;
import cn.est.config.WechatConfig;
import cn.est.constants.ResultEnum;
import cn.est.dto.UsersDto;
import cn.est.pojo.Users;
import cn.est.constants.Constants;
import cn.est.dto.Page;
import cn.est.dto.Result;
import cn.est.service.UsersService;
import cn.est.utils.EmptyUtils;
import cn.est.utils.MyCollectionUtils;
import cn.est.utils.ResultUtils;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.est.utils.UrlUtils;
import cn.est.utils.redis.RedisKeyUtils;
import cn.est.utils.redis.RedisUtils;
import com.alibaba.fastjson.JSON;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.util.Map;

@Controller
@RequestMapping("/client/users")
public class UsersController {
    Logger log = LoggerFactory.getLogger(UsersController.class);
    @Resource
    private UsersService usersService;
    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private WechatConfig wechatConfig;

    /**
     * 短信登录、注册
     *
     * @param phone
     * @param sms
     * @return
     */
    @ApiOperation(value = "短信验证码登录、注册", produces = "application/json", notes = "使用短信验证码进行快速登陆或注册。")
    @ApiImplicitParams({@ApiImplicitParam(name = "phone", value = "手机号码", required = true, dataType = "String")
            , @ApiImplicitParam(name = "sms", value = "验证码", required = true, dataType = "String")})
    @PostMapping("/login/sms")
    public Result<Map<String, Object>> login(String phone, String sms) {
        log.info("短信登录,phone={}，smsCode:{}", phone, sms);
        Result<Map<String, Object>> result = null;
        // 1.判断手机号是否正确
        if (!checkPhone(phone)) {
            log.info("手机号码错误phone:{}", phone);
            return ResultUtils.returnFail("手机号码错误", ResultEnum.FAIL_PARAM.getCode());
        }
        // 2.校验验证码
        if (!checkSmsCode(phone, Constants.Sms.TYPE_REGIST_OR_LOGIN, sms)) {
            log.info("验证码错误phone:{}，smsCode:{}", phone, sms);
            return ResultUtils.returnResult(ResultEnum.FAIL_VERIFY);
        }
        // login
        UsersDto usersVo = usersService.loginByPhone(phone);
        if (usersVo != null) {
            result = ResultUtils.returnDataSuccess(MyCollectionUtils.createSimpleMap("token", usersVo.getToken()));
        } else {
            result = ResultUtils.returnResult(ResultEnum.FAIL_ACCOUNT_NOT_EXIST);
        }
        return result;
    }

    /**
     * 微信登录——第一步：获取code
     * @param response
     */
    @ApiOperation(value = "微信登陆、注册", produces = "application/json", notes = "使用微信扫码进行快速登陆或注册。")
    @GetMapping(value = "/login/wechat")
    public void wechatLogin(HttpServletResponse response){
        try {
            StringBuilder openBuilder = new StringBuilder(wechatConfig.getOpen_url())
                    .append("?").append("appid=").append(wechatConfig.getAppid())
                    .append("&").append("redirect_uri=").append(wechatConfig.getRedirect_uri())
                    .append("&").append("response_type=").append(wechatConfig.getGrant_type())
                    .append("&").append("scope=").append(wechatConfig.getScope())
                    .append("&").append("state=").append(wechatConfig.getState());
            response.sendRedirect(openBuilder.toString());
        } catch (Exception e) {
            log.error("唤起微信登录页面失败:{}", e);
        }

    }
    /**
     * 微信登录——第二步：通过code换取access_token
     * @param code
     * @param request
     * @param response
     * @throws IOException
     */
    @GetMapping(value = "/wechat/callback")
    public void wechatCallback(@RequestParam String code, HttpServletRequest request, HttpServletResponse response) throws IOException{
        StringBuilder accessTokenBuilder = new StringBuilder(wechatConfig.getAccess_token_url())
                .append("?").append("appid=").append(wechatConfig.getAppid())
                .append("&").append("secret=").append(wechatConfig.getSecret())
                .append("&").append("code=").append(code)
                .append("&").append("grant_type=").append(wechatConfig.getGrant_type());
        response.setContentType("text/html;charset=utf-8");
        String json = UrlUtils.loadURL(accessTokenBuilder.toString());
        Map<String,Object> wechatToken = JSON.parseObject(json, Map.class);
        try {
            //验证本地库是否存在该用户
            String openId = wechatToken.get("openid").toString();
            String accessToken = wechatToken.get("access_token").toString();
            UsersDto user = usersService.loginByWechat(accessToken, openId);
            String token = user.getToken();
            //返回前端处理
            String loginPage = wechatConfig.getSuccess_url() + "?token=" + token;
            response.sendRedirect(loginPage);
        } catch (Exception e) {
            log.error("微信回调错误：{}" , e);
        }
    }


    @RequestMapping("/search")
    @ResponseBody
    public Page<Users> searchUsers(@RequestParam Map<String,Object> param) {
        Page<Users> usersPage = null;
        try {
            Integer pageNo= EmptyUtils.isEmpty(param.get("pageNo"))? Page.DEFAULT_PAGE_NO:Integer.parseInt((String) param.get("pageNo"));
            Integer pageSize= EmptyUtils.isEmpty(param.get("pageSize"))? Page.DEFAULT_PAGE_SIZE:Integer.parseInt((String) param.get("pageSize"));
            usersPage  = usersService.queryUsersPageByMap(param, pageNo, pageSize);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return usersPage;
    }

    @RequestMapping("/saveOrUpdateUsers")
    @ResponseBody
    public Result saveOrUpdateUsers(Users users){
        Integer flag=0;
        try {
            if(EmptyUtils.isEmpty(users.getId())){
                flag=usersService.qdtxAddUsers(users);
            }else{
                flag=usersService.qdtxModifyUsers(users);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag>=1?ResultUtils.returnSuccess():ResultUtils.returnFail();
    }

    @RequestMapping("/getUsersById")
    @ResponseBody
    public Result getUsersById(Long id){
        Result result= ResultUtils.returnSuccess();
        Users users=null;
        try {
            users=usersService.getUsersById(id);
            result.setData(users);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    @RequestMapping("/batchRemoveUsers")
    @ResponseBody
    public Result batchRemoveUsers(String ids){
        Integer flag=0;
        try {
            flag=usersService.qdtxBatchDeleteUsers(ids);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ResultUtils.returnSuccess();
    }

    @RequestMapping("/removeUsersById")
    @ResponseBody
    public Result removeUsersById(Long id){
        Integer flag=0;
        try {
            flag=usersService.qdtxDeleteUsersById(id);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ResultUtils.returnSuccess();
    }

    /**
     * 验证手机号
     *
     * @param phone
     */
    private boolean checkPhone(String phone) {
        return phone.matches(Constants.PHONE_REGSTR);
    }


    /**
     * 验证验证码
     *
     * @param phone
     * @param codeType
     */
    private boolean checkSmsCode(String phone, Integer codeType, String sms) {
        String value = getVerifyCodeFromRedis(phone, codeType);
        return sms.equals(value);
    }

    /**
     * 从reids中获取验证码
     *
     * @param phone
     * @param codeType
     */
    public String getVerifyCodeFromRedis(String phone, Integer codeType) {
        String key = RedisKeyUtils.formatKeyWithPrefix(Constants.Redis.PREFIX_SMS, codeType.toString(), phone);
        return redisUtils.getValue(key);
    }


}
